#!/bin/bash

# 加载所有依赖模块
source "$(dirname "${BASH_SOURCE[0]}")/common.sh"
source "$(dirname "${BASH_SOURCE[0]}")/docker.sh"
source "$(dirname "${BASH_SOURCE[0]}")/build.sh"
source "$(dirname "${BASH_SOURCE[0]}")/health.sh"

# 创建或更新服务
create_or_update_service() {
    local image_name="$1"
    local service_name="$2"
    local container_port="$3"
    local host_port="$4"
    local replicas="$5"
    local profile="$6"
    local health_enabled="$7"
    local health_endpoint="$8"
    local cpu_limit="$9"
    local cpu_request="${10}"
    local mem_limit="${11}"
    local mem_request="${12}"
    
    # 检查服务是否存在
    local service_exists
    service_exists=$(check_service_exists "$service_name")
    
    if [ -z "$service_exists" ]; then
        # 创建新服务
        start_spinner "正在创建服务..." >&2
        debug "执行服务创建命令: docker service create --name $service_name --replicas $replicas --publish $host_port:$container_port ..." >&2
        
        # 执行服务创建命令
        local cmd_output
        if ! cmd_output=$(docker service create \
            --name "$service_name" \
            --replicas "$replicas" \
            --publish "$host_port:$container_port" \
            --update-parallelism 1 \
            --update-delay 10s \
            --update-failure-action rollback \
            --update-order start-first \
            --update-monitor 30s \
            --limit-cpu "$cpu_limit" \
            --reserve-cpu "$cpu_request" \
            --limit-memory "$mem_limit" \
            --reserve-memory "$mem_request" \
            -e "SPRING_PROFILES_ACTIVE=$profile" \
            -e "SERVER_PORT=$container_port" \
            -e "JAVA_OPTS=-Xmx$(echo "$mem_limit" | sed 's/G/g/;s/M/m/')" \
            "$image_name:$IMAGE_TAG" 2>&1); then
            stop_spinner "error" "服务创建失败" >&2
            debug "创建失败输出: $cmd_output" >&2
            handle_error "服务创建失败: $cmd_output"
        fi
        
        debug "服务创建成功: $cmd_output" >&2
        stop_spinner "success" "服务创建完成" >&2
    else
        # 检查是否有挂载点变化，如果有则需要重新创建服务
        local need_recreate=false
        if [ ${#mounts[@]} -gt 0 ]; then
            # 获取当前服务的挂载点信息
            local current_mounts
            current_mounts=$(docker service inspect "$service_name" --format '{{range .Spec.TaskTemplate.ContainerSpec.Mounts}}{{.Type}},source={{.Source}},target={{.Target}} {{end}}' 2>/dev/null || echo "")

            # 比较挂载点是否有变化
            local new_mounts_str=""
            for mount in "${mounts[@]}"; do
                new_mounts_str+="$mount "
            done

            if [ "$current_mounts" != "$new_mounts_str" ]; then
                need_recreate=true
                debug "检测到挂载点变化，需要重新创建服务" >&2
            fi
        fi

        if $need_recreate; then
            # 删除现有服务并重新创建
            start_spinner "检测到挂载点变化，正在重新创建服务..." >&2
            debug "删除现有服务: $service_name" >&2

            if ! docker service rm "$service_name" >/dev/null 2>&1; then
                stop_spinner "error" "删除现有服务失败" >&2
                handle_error "删除现有服务失败"
            fi

            # 等待服务完全删除
            sleep 3

            # 重新创建服务
            debug "重新创建服务: $service_name" >&2
            local cmd_output
            # 构建挂载点参数
            local mount_args=()
            for mount in "${mounts[@]}"; do
                mount_args+=(--mount "$mount")
            done

            if ! cmd_output=$(docker service create \
                "${mount_args[@]}" \
                --name "$service_name" \
                --replicas "$replicas" \
                --publish "$host_port:$container_port" \
                --update-parallelism 1 \
                --update-delay 10s \
                --update-failure-action rollback \
                --update-order start-first \
                --update-monitor 30s \
                --limit-cpu "$cpu_limit" \
                --reserve-cpu "$cpu_request" \
                --limit-memory "$mem_limit" \
                --reserve-memory "$mem_request" \
                -e "SPRING_PROFILES_ACTIVE=$profile" \
                -e "SERVER_PORT=$container_port" \
                -e "JAVA_OPTS=-Xmx$(echo "$mem_limit" | sed 's/G/g/;s/M/m/')" \
                "$image_name:$IMAGE_TAG" 2>&1); then
                stop_spinner "error" "服务重新创建失败" >&2
                debug "重新创建失败输出: $cmd_output" >&2
                handle_error "服务重新创建失败: $cmd_output"
            fi

            debug "服务重新创建成功: $cmd_output" >&2
            stop_spinner "success" "服务重新创建完成" >&2
        else
            # 更新现有服务（不涉及挂载点变化）
            start_spinner "正在更新服务..." >&2
            debug "执行服务更新命令: docker service update --image $image_name:$IMAGE_TAG $service_name ..." >&2

            # 执行服务更新命令
            local cmd_output
            if ! cmd_output=$(docker service update \
                --image "$image_name:$IMAGE_TAG" \
                --update-parallelism 1 \
                --update-delay 10s \
                --update-failure-action rollback \
                --update-order start-first \
                --update-monitor 30s \
                --limit-cpu "$cpu_limit" \
                --reserve-cpu "$cpu_request" \
                --limit-memory "$mem_limit" \
                --reserve-memory "$mem_request" \
                --env-add "JAVA_OPTS=-Xmx$(echo "$mem_limit" | sed 's/G/g/;s/M/m/')" \
                --force \
                "$service_name" 2>&1); then
                stop_spinner "error" "服务更新失败" >&2
                debug "更新失败输出: $cmd_output" >&2
                handle_error "服务更新失败: $cmd_output"
            fi

            debug "服务更新成功: $cmd_output" >&2
            stop_spinner "success" "服务更新完成" >&2
        fi
    fi
}

# 监控部署状态
monitor_deployment() {
    local service_name="$1"
    local host_port="$2"
    local health_endpoint="$3"
    local health_enabled="$4"
    local image_name="$5"
    
    start_spinner "等待服务启动..." >&2
    local timeout=300  # 5分钟超时
    local start_time=$(date +%s)
    
    while true; do
        local current_time=$(date +%s)
        local elapsed=$((current_time - start_time))
        
        if [ $elapsed -gt $timeout ]; then
            stop_spinner "error" "部署超时" >&2
            handle_error "部署超时"
        fi
        
        # 获取服务状态
        local service_status
        service_status=$(get_service_status "$service_name")
        if [ $? -ne 0 ]; then
            stop_spinner "error" "无法获取服务信息" >&2
            handle_error "无法获取服务信息"
        fi
        
        # 获取副本状态
        local replicas
        replicas=$(get_service_replicas "$service_name")
        local replicas_running=$(echo "$replicas" | cut -d'/' -f1)
        local desired_replicas=$(echo "$replicas" | cut -d'/' -f2)
        
        if [ "$service_status" = "completed" ] || [ "$service_status" = "running" ]; then
            if [ "$replicas_running" = "$desired_replicas" ]; then
                stop_spinner "success" "服务已启动 ($replicas_running/$desired_replicas)" >&2
                
                # 检查服务健康状态
                if $health_enabled; then
                    if wait_for_health "$service_name" "$host_port" "$health_endpoint" "$health_enabled"; then
                        DEPLOY_SUCCESS=true
                        show_deployment_success "$service_name" "$host_port" "$image_name:$IMAGE_TAG"
                        
                        # 清理无效镜像
                        cleanup_images "$image_name"
                        
                        cleanup
                        return 0
                    fi
                else
                    DEPLOY_SUCCESS=true

                    # 清理无效镜像
                    cleanup_images "$image_name"

                    # 清理临时文件
                    cleanup

                    # 显示成功信息
                    show_deployment_success "$service_name" "$host_port" "$image_name:$IMAGE_TAG"

                    return 0
                fi
            fi
        elif [ "$service_status" = "rollback_completed" ]; then
            stop_spinner "error" "部署失败，已回滚" >&2
            handle_error "部署失败，服务已回滚"
        fi
        
        sleep 2
    done
}

# 显示部署成功信息
show_deployment_success() {
    local service_name="$1"
    local host_port="$2"
    local image="$3"
    
    {
        success "服务访问地址: ${CYAN}http://0.0.0.0:$host_port${NC}"
        success "查看服务状态: ${CYAN}docker service ps $service_name${NC}"
        success "部署镜像: ${CYAN}$image${NC}"
    } >&2
}

# 执行部署
do_deploy() {
    local service_name="$1"
    local container_port="${2:-8080}"
    local host_port="$3"
    local replicas="$4"
    local profile="$5"
    local health_enabled="$6"
    local health_endpoint="$7"
    local cpu_limit="$8"
    local cpu_request="$9"
    local mem_limit="${10}"
    local mem_request="${11}"
    local target_path="${12}"
    shift 12
    local mounts=("$@")

    # 检查必要条件
    check_docker
    init_swarm

    # 执行构建并获取镜像标签
    do_build "$service_name" "$target_path" >/dev/null

    # 创建或更新服务
    create_or_update_service \
        "$service_name" \
        "$service_name" \
        "$container_port" \
        "$host_port" \
        "$replicas" \
        "$profile" \
        "$health_enabled" \
        "$health_endpoint" \
        "$cpu_limit" \
        "$cpu_request" \
        "$mem_limit" \
        "$mem_request" \
        "${mounts[@]}"

    # 监控部署状态
    monitor_deployment \
        "$service_name" \
        "$host_port" \
        "$health_endpoint" \
        "$health_enabled" \
        "$service_name"
}
